package com.xscr.api.controller;

import java.io.BufferedOutputStream;
import java.io.StringReader;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.xml.sax.InputSource;

import com.rop.response.Response;
import com.xscr.api.utils.CodeUtil;
import com.xscr.api.utils.GetWxOrderno;
import com.xscr.api.utils.IpUtil;
import com.xscr.api.utils.RequestHandler;
import com.xscr.api.utils.Sha1Util;
import com.xscr.api.utils.TenpayUtil;
import com.xscr.order.api.OrderFormService;
import com.xscr.order.api.OrderItemService;
import com.xscr.order.api.OrderPayDetailService;
import com.xscr.order.po.OrderForm;
import com.xscr.order.po.OrderPayDetail;
import com.xscr.wxpay.dto.WxPayDto;
import com.xscr.wxpay.dto.WxPayResult;

@Controller
@RequestMapping("/pay")
public class WxPayController{
	
	    private static final Logger logger=LoggerFactory.getLogger(WxPayController.class);
		@Autowired
		private OrderFormService orderFormService;
		@Autowired
		private OrderPayDetailService orderPayDetailService;
		@Autowired
		private OrderItemService orderItemService;
		
		
		//微信支付商户开通后 微信会提供appid和appsecret和商户号partner
		private static String appid = "wx26c8dd3b51cf8542";
		private static String appsecret = "4d67536aa81fee23fdf7752c048d9d4c";
		private static String partner = "1292680201";
		//这个参数partnerkey是在商户后台配置的一个32位的key,微信商户平台-账户设置-安全设置-api安全
		private static String partnerkey = "a25b71515325401e4949210fe8f4e728";

		@RequestMapping("/getWxPayPackage")
		public Response getWxPayPackage(Integer orderId,Model model,HttpServletRequest request){
			Response response = new Response();	
			OrderForm order = orderFormService.selectByOrderId(orderId);
			String path = request.getContextPath();
			String basePath = request.getScheme()+ "://"+ request.getServerName()+ (request.getServerPort() != 80 ? ":"+ request.getServerPort() : "") + path;
			Map<String, Object> data = new HashMap<String, Object>(5);
			
			if(null != order && order.getOrderStatus() == 1){
				
				WxPayDto tpWxPay = new WxPayDto();
			    tpWxPay.setBody("秀色成人商品信息");
			    tpWxPay.setOrderId(CodeUtil.getpayOrderId(order.getOrderId()));
			    //tpWxPay.setOrderId(getNonceStr());
			    tpWxPay.setSpbillCreateIp(IpUtil.getIpAddrByRequest(request));
			    tpWxPay.setNotifyUrl(basePath+"/pay/wxnotify");
			    //TODO
			    tpWxPay.setTotalFee("0.01");
//			    tpWxPay.setTotalFee(order.getPaidPrice().doubleValue()+order.getPostage().doubleValue());
//				String codeurl = getCodeurl(tpWxPay);
				String finaPackage=getPackage(tpWxPay);
				logger.info("扫码支付 ： "+finaPackage);
				data.put("finaPackage", finaPackage);
				response.setData(data);
				response.getResult().setResult("1");
				response.getResult().setMessage("获取预支付成功");
				return response;
			}			
			return response;
		}
		
		
		@RequestMapping("/wxnotify")
		public void wxnotify(HttpServletRequest request,HttpServletResponse response){
			String inputLine;
			String notityXml = "";
			String resXml = "";

			try {
				while ((inputLine = request.getReader().readLine()) != null) {
					notityXml += inputLine;
				}
				request.getReader().close();
			} catch (Exception e) {
				e.printStackTrace();
			}

			System.out.println("接收到的报文：" + notityXml);
			
			Map<String, String> m = parseXmlToList2(notityXml);
			
			if("SUCCESS".equals(m.get("result_code"))){
				//支付成功
				resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
				+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
			}else{
				resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
				+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
			}
			
			Integer orderId = Integer.parseInt(m.get("out_trade_no"));
			String ip = m.get("spbill_create_ip");

			/**
			 * 更新订单信息.
			 */
			try {
				this.payAfter(orderId,ip);
			
				System.out.println("微信支付回调数据结束");
	
				BufferedOutputStream out = new BufferedOutputStream(
						response.getOutputStream());
				out.write(resXml.getBytes());
				out.flush();
				out.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
		
		
		/**
		 * @Description:支付完成更新订单信息
		 * @param orderId 订单id
		 * @throws Exception
		 * @throws
		 */
		private void payAfter(Integer orderIds,String ip) throws Exception{
			final OrderForm orderForm = orderFormService.selectById(orderIds);
			final Integer orderId =orderIds;
			if(orderForm!=null&&orderForm.getOrderStatus()<2){
				//更新订单表
			    orderForm.setOrderStatus(2);
				orderFormService.update(orderForm);
				
				/**
				 * 插入流水.
				 */
				OrderPayDetail orderPayDetail = new OrderPayDetail();
				orderPayDetail.setPaymentTime(new Date());
				orderPayDetail.setPaymentType(0);
				orderPayDetail.setOrderId(orderId);
				orderPayDetail.setPaymentMethod(3);
				orderPayDetail.setPaymentSource(0);
				orderPayDetail.setPaymentIp(ip);
				orderPayDetail.setOrderAmount(orderForm.getPaidPrice());
				orderPayDetail.setPayWaterCode(CodeUtil.getpayOrderCode(orderForm.getOrderCode()));
				orderPayDetailService.insert(orderPayDetail);
				new Thread(new Runnable() {
					@Override
					public void run() {
						try {
							orderItemService.reduceStock(orderForm, 2);
						} catch (Exception e) {
							e.printStackTrace();
						}
						
					}
				}).start();	
			}
		}
		
		
		/**
		 * 获取微信扫码支付二维码连接
		 */
		private static String getCodeurl(WxPayDto tpWxPayDto){
			
			// 1 参数
			// 订单号
			String orderId = tpWxPayDto.getOrderId();
			// 附加数据 原样返回
			String attach = "";
			// 总金额以分为单位，不带小数点
			String totalFee = getMoney(tpWxPayDto.getTotalFee());
			
			// 订单生成的机器 IP
			String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
			// 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
			String notify_url = tpWxPayDto.getNotifyUrl();
			String trade_type = "NATIVE";

			// 商户号
			String mch_id = partner;
			// 随机字符串
			String nonce_str = getNonceStr();

			// 商品描述根据情况修改
			String body = tpWxPayDto.getBody();

			// 商户订单号
			String out_trade_no = orderId;

			SortedMap<String, String> packageParams = new TreeMap<String, String>();
			packageParams.put("appid", appid);
			packageParams.put("mch_id", mch_id);
			packageParams.put("nonce_str", nonce_str);
			packageParams.put("body", body);
			packageParams.put("attach", attach);
			packageParams.put("out_trade_no", out_trade_no);

			// 这里写的金额为1 分到时修改
			packageParams.put("total_fee", totalFee);
			packageParams.put("spbill_create_ip", spbill_create_ip);
			packageParams.put("notify_url", notify_url);

			packageParams.put("trade_type", trade_type);

			RequestHandler reqHandler = new RequestHandler(null, null);
			reqHandler.init(appid, appsecret, partnerkey);

			String sign = reqHandler.createSign(packageParams);
			String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>"
					+ mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
					+ "</nonce_str>" + "<sign>" + sign + "</sign>"
					+ "<body><![CDATA[" + body + "]]></body>" 
					+ "<out_trade_no>" + out_trade_no
					+ "</out_trade_no>" + "<attach>" + attach + "</attach>"
					+ "<total_fee>" + totalFee + "</total_fee>"
					+ "<spbill_create_ip>" + spbill_create_ip
					+ "</spbill_create_ip>" + "<notify_url>" + notify_url
					+ "</notify_url>" + "<trade_type>" + trade_type
					+ "</trade_type>" + "</xml>";
			String code_url = "";
			String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
			
			
			code_url = new GetWxOrderno().getCodeUrl(createOrderURL, xml);
			System.out.println("code_url----------------"+code_url);
			
			return code_url;
		}
		
		
		/**
		 * 获取请求预支付id报文
		 * @return
		 */
		@SuppressWarnings("static-access")
		private static String getPackage(WxPayDto tpWxPayDto) {
			
			String openId = tpWxPayDto.getOpenId();
			// 1 参数
			// 订单号
			String orderId = tpWxPayDto.getOrderId();
			// 附加数据 原样返回
			String attach = "";
			// 总金额以分为单位，不带小数点
			String totalFee = getMoney(tpWxPayDto.getTotalFee());
			
			// 订单生成的机器 IP
			String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
			// 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
			String notify_url = "";
			String trade_type = "NATIVE";

			// ---必须参数
			// 商户号
			String mch_id = partner;
			// 随机字符串
			String nonce_str = getNonceStr();

			// 商品描述根据情况修改
			String body = tpWxPayDto.getBody();

			// 商户订单号
			String out_trade_no = orderId;

			SortedMap<String, String> packageParams = new TreeMap<String, String>();
			packageParams.put("appid", appid);
			packageParams.put("mch_id", mch_id);
			packageParams.put("nonce_str", nonce_str);
			packageParams.put("body", body);
			packageParams.put("attach", attach);
			packageParams.put("out_trade_no", out_trade_no);

			// 这里写的金额为1 分到时修改
			packageParams.put("total_fee", totalFee);
			packageParams.put("spbill_create_ip", spbill_create_ip);
			packageParams.put("notify_url", notify_url);

			packageParams.put("trade_type", trade_type);
			packageParams.put("openid", openId);

			RequestHandler reqHandler = new RequestHandler(null, null);
			reqHandler.init(appid, appsecret, partnerkey);

			String sign = reqHandler.createSign(packageParams);
			String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>"
					+ mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
					+ "</nonce_str>" + "<sign>" + sign + "</sign>"
					+ "<body><![CDATA[" + body + "]]></body>" 
					+ "<out_trade_no>" + out_trade_no
					+ "</out_trade_no>" + "<attach>" + attach + "</attach>"
					+ "<total_fee>" + totalFee + "</total_fee>"
					+ "<spbill_create_ip>" + spbill_create_ip
					+ "</spbill_create_ip>" + "<notify_url>" + notify_url
					+ "</notify_url>" + "<trade_type>" + trade_type
					+ "</trade_type>" + "<openid>" + openId + "</openid>"
					+ "</xml>";
			String prepay_id = "";
			String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
			
			
			prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);

			System.out.println("获取到的预支付ID：" + prepay_id);
			
			
			//获取prepay_id后，拼接最后请求支付所需要的package
			
			SortedMap<String, String> finalpackage = new TreeMap<String, String>();
			String timestamp = Sha1Util.getTimeStamp();
			String packages = "prepay_id="+prepay_id;
			finalpackage.put("appId", appid);  
			finalpackage.put("timeStamp", timestamp);  
			finalpackage.put("nonceStr", nonce_str);  
			finalpackage.put("package", packages);  
			finalpackage.put("signType", "MD5");
			//要签名
			String finalsign = reqHandler.createSign(finalpackage);
			
			String finaPackage = "\"appId\":\"" + appid + "\",\"timeStamp\":\"" + timestamp
			+ "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\""
			+ packages + "\",\"signType\" : \"MD5" + "\",\"paySign\":\""
			+ finalsign + "\"";

			System.out.println("V3 jsApi package:"+finaPackage);
			return finaPackage;
		}

		/**
		 * 获取随机字符串
		 * @return
		 */
		private static String getNonceStr() {
			// 随机数
			String currTime = TenpayUtil.getCurrTime();
			// 8位日期
			String strTime = currTime.substring(8, currTime.length());
			// 四位随机数
			String strRandom = TenpayUtil.buildRandom(4) + "";
			// 10位序列号,可以自行调整。
			return strTime + strRandom;
		}

		/**
		 * 元转换成分
		 * @param money
		 * @return
		 */
		private static String getMoney(String amount) {
			if(amount==null){
				return "";
			}
			// 金额转化为分为单位
			String currency =  amount.replaceAll("\\$|\\￥|\\,", "");  //处理包含, ￥ 或者$的金额  
	        int index = currency.indexOf(".");  
	        int length = currency.length();  
	        Long amLong = 0l;  
	        if(index == -1){  
	            amLong = Long.valueOf(currency+"00");  
	        }else if(length - index >= 3){  
	            amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));  
	        }else if(length - index == 2){  
	            amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);  
	        }else{  
	            amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");  
	        }  
	        return amLong.toString(); 
		}
		
		
		/**
		 * description: 解析微信通知xml
		 * 
		 * @param xml
		 * @return
		 * @author ex_yangxiaoyi
		 * @see
		 */
		@SuppressWarnings({ "unused", "rawtypes", "unchecked" })
		private static Map<String, String> parseXmlToList2(String xml) {
			Map<String,String> retMap = new HashMap();
			try {
				StringReader read = new StringReader(xml);
				// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
				InputSource source = new InputSource(read);
				// 创建一个新的SAXBuilder
				SAXBuilder sb = new SAXBuilder();
				// 通过输入源构造一个Document
				Document doc = (Document) sb.build(source);
				Element root = doc.getRootElement();// 指向根节点
				List<Element> es = root.getChildren();
				if (es != null && es.size() != 0) {
					for (Element element : es) {
						retMap.put(element.getName(), element.getValue());
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return retMap;
		}

	}
